﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DLC.Module.DataTable;
using DLC.Module.DataTable.Default;
using System.IO;
using System.Reflection;
using System.Text;
using System;

namespace DLC.Module.DataTable.ArchiveBytes
{
    public class DataTableBytes<T> : DataTable<T>, IDataTableBytes where T : class, IDataRow, new()
    {
        public byte[] ToBytes()
        {
            using(MemoryStream stream = new MemoryStream())
            {
                using (BinaryWriter binary = new BinaryWriter(stream, Encoding.UTF8))
                {
                    PropertyInfo[] p = Type.GetProperties();
                    var dataRows = GetAllDataRows();
                    binary.Write(dataRows.Length);
                    foreach (var dataRow in dataRows)
                    {
                        binary.Write((object)GetRowBytes(dataRow));
                    }
                }
                return stream.ToArray();
            }
        }
        private byte[] GetRowBytes(T dataRow)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                using (BinaryWriter binary = new BinaryWriter(stream, Encoding.UTF8))
                {
                    PropertyInfo[] p = Type.GetProperties();
                    for (int i = 0; i < p.Length; i++)
                    {
                        var property = p[i];
                        var value = property.GetValue(dataRow, null);
                        binary.Write(value);
                    }
                    return stream.ToArray();
                }
            }
        }
        private T ParseRowFromBytes(byte[] data)
        {
            PropertyInfo[] p = Type.GetProperties();
            var dataRow = (T)Activator.CreateInstance(Type);
            using (MemoryStream rowStream = new MemoryStream(data))
            {
                using (BinaryReader rowBinary = new BinaryReader(rowStream, Encoding.UTF8))
                {
                    for (int i = 0; i < p.Length; i++)
                    {
                        try
                        {
                            var property = p[i];
                            property.SetValue(dataRow, rowBinary.Read(property.PropertyType));
                        }
                        catch (Exception e)
                        {
                            Debug.LogError($"ParseFromBytes Error. Deserialize Exception: {e.Message} at {i}");
                        }
                    }
                }
            }
            return dataRow;
        }
        public bool ParseFromBytes(byte[] data)
        {
            using (MemoryStream stream = new MemoryStream(data))
            {
                using (BinaryReader binary = new BinaryReader(stream, Encoding.UTF8))
                {

                    int count = binary.ReadInt32();
                    for (int j = 0; j < count; j++)
                    {
                        byte[] bytesRow = (byte[])binary.Read(typeof(byte[]));
                        AddDataRow(ParseRowFromBytes(bytesRow));
                    }
                }
            }
            return true;
        }

    }
}
